import { _decorator, bits, clamp, Collider2D, Color, Component, Contact2DType, instantiate, Node, toDegree, toRadian, tween, Vec2, Vec3 } from 'cc';
import { Constant } from './Constant';
import { Util } from './Util';
import { Const } from './Const';
import { Weapon } from './Weapon';
import { PoolManager } from './PoolManager';
import { SurroundSword } from './SurroundSword';
import { Global } from './Global';
import { Lightning } from './Lightning';
import { Bullet } from './Bullet';
const { ccclass, property } = _decorator;

@ccclass('Player')
export class Player extends Component {
    @property(Node)
    private ndAnim: Node;
    @property(Node)
    private ndGun0: Node;
    @property(Node)
    private ndShootk: Node;

    public isAiming: boolean = true;

    public shootPos = new Vec3();

    speed: number = 2;
    moveDirection: number = 0;
    isMoving: boolean = false;
    attackDirection: number = 0;


    protected onEnable(): void {
        const collider = this.node.getComponent(Collider2D);
        if (collider) {
            collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
            collider.on(Contact2DType.END_CONTACT, this.onEndContact, this);
        }
    }

    protected onDisable(): void {
        const collider = this.node.getComponent(Collider2D);
        if (collider) {
            collider.off(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
            collider.off(Contact2DType.END_CONTACT, this.onEndContact, this);
        }
        this.unscheduleAllCallbacks();
    }

    start() {
        this.isMoving = false;
        this.schedule(() => {
            const nearestNode = this.getNearestEnemy();
            if (nearestNode) {
                this.attackDirection = Util.getRadian(this.node.worldPosition, nearestNode.worldPosition);
                this.isAiming && this.setGunAngel(toDegree(this.attackDirection));
            }
        }, 0.1)
    }

    onBeginContact(self: Collider2D, other: Collider2D) {
        if (other.group === Constant.ColliderGroup.ENEMY) {
            Util.showDamageText('10', Color.RED.toString(), this.node.worldPosition, Const.ndDamageTextParent);
        }
    }


    onEndContact(self: Collider2D, other: Collider2D) {

    }

    update(deltaTime: number) {
        if (this.isMoving) {
            let x = this.node.position.x + Math.cos(this.moveDirection) * this.speed;
            let y = this.node.position.y + Math.sin(this.moveDirection) * this.speed;
            x = clamp(x, -1024, 1024);
            y = clamp(y, -1024, 1024);

            this.node.setPosition(x, y);

            const degree = toDegree(this.moveDirection);
            if (degree >= -90 && degree <= 90) {
                this.ndAnim.setScale(1, 1)
            } else {
                this.ndAnim.setScale(-1, 1)
            }
        }
    }


    startEndlessArrow() {
        const tw = tween(this.node)
            .delay(0.5)
            .call(() => {
                const ndArrow = Global.getNode(Constant.PrefabUrl.ARROW, Const.ndWeapon);
                ndArrow.worldPosition = this.node.worldPosition;
                ndArrow.angle = toDegree(this.attackDirection);
                const wp = ndArrow.getComponent(Weapon);
                wp.isMoving = true;
                wp.moveDirection = this.attackDirection;
                wp.speed = 12;
            });
        tween(this.node).repeatForever(tw).start();
    }

    startSurrondingSwords() {
        const ndSurroundSword = Global.getNode(Constant.PrefabUrl.SURROUNDSWORD, Const.ndWeapon);
        ndSurroundSword.getComponent(SurroundSword).isMoving = true;
    }

    castFireBall(radian: number) {
        const ndFireBall = Global.getNode(Constant.PrefabUrl.FIRE_BALL, Const.ndWeapon);
        ndFireBall.worldPosition = this.node.worldPosition;
        ndFireBall.angle = toDegree(radian)
        const wp = ndFireBall.getComponent(Weapon);
        wp.isMoving = true;
        wp.attack = 15;
        wp.speed = 10;
        wp.moveDirection = radian;

        return ndFireBall;
    }

    startFireBall() {
        const tw = tween(this.node)
            .delay(1)
            .call(() => {
                const deltaAngle = 30;
                const startDegree = toDegree(this.attackDirection) - deltaAngle;
                for (let i = 0; i < 3; i++) {
                    const node = this.castFireBall(toRadian(startDegree + deltaAngle * i));
                    node.angle = startDegree + deltaAngle * i;
                }
            });
        tween(this.node).repeatForever(tw).start();
    }

    startLightning() {
        const tw = tween(this.node)
            .delay(1)
            .call(() => {
                for (let i = 0; i < 1; i++) {
                    const nearestNode = this.getNearestEnemy();
                    if (nearestNode) {
                        const ndLightning = Global.getNode(Constant.PrefabUrl.LIGHTNING, Const.ndWeapon);
                        ndLightning.worldPosition = nearestNode.worldPosition;
                        const wp = ndLightning.getComponent(Lightning);
                        wp.attack = 10;
                        wp.startLightning();
                    }
                }
            });
        tween(this.node).repeatForever(tw).start();
    }

    startShootBullet() {
        const tw = tween(this.node)
            .call(() => {
                const ndBullet = Global.getNode(Constant.PrefabUrl.BULLET, Const.ndWeapon);
                ndBullet.worldPosition = this.getShootPosition();
                const wp = ndBullet.getComponent(Bullet);
                wp.isMoving = true;
                wp.moveDirection = toRadian(this.ndGun0.angle);
                wp.speed = 20;
            })
            .delay(0.2)
        tween(this.node).repeatForever(tw).start();
    }


    /**得到距离最近的敌人 */
    getNearestEnemy() {
        const enemys = Const.ndEnemyParent.children;
        let min = bits.INT_MAX;
        let targetNode: Node = null;
        for (let i = 0; i < enemys.length; i++) {
            const distance = Vec2.distance(enemys[i].worldPosition, this.node.worldPosition);
            if (distance < min) {
                targetNode = enemys[i];
            }
        }
        return targetNode;
    }

    setGunAngel(angle: number) {
        this.ndGun0.angle = angle;
    }

    getShootPosition() {
        return this.ndShootk.worldPosition;
    }


}


